﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Collections;

namespace Wilke.SharePoint.Tools
{
    public partial class AddWebConfigModificationForm : Form
    {
        #region Private Members

        private bool validatingAll = false;

        #endregion

        #region Properties

        private XmlDocument XmlDocument { get; set; }
        private Dictionary<int, string> ParentNodes { get; set; }
        public WebConfigModification WebConfigModification { get; set; }

        #endregion

        #region Construction

        public AddWebConfigModificationForm(XmlDocument xmlDocument)
        {
            InitializeComponent();
            this.XmlDocument = xmlDocument;
        }

        #endregion

        #region Event Handlers

        private void WizardForm_Load(object sender, EventArgs e)
        {
            AutoCompleteStringCollection autoCompleteStringCollection = new AutoCompleteStringCollection();

            textBoxModificationOwner.Text = ConfigurationHelper.DefaultOwner;

            UpdateModifiationPathAutoComplete();
            
            UpdateFrequentlyUsedNodeNamesAutoComplete();

            dropDownModificationType.SelectedIndex = 0;
        }

        private void textBoxModificationPath_Leave(object sender, EventArgs e)
        {
            switch (dropDownModificationType.Text)
            {
                case "EnsureChildNode":
                    break;
                case "EnsureSection":
                    break;
                case "EnsureAttribute":
                    dropDownAttributeName.Items.Clear();
                    if (!String.IsNullOrEmpty(textBoxModificationPath.Text))
                    {
                        XmlNode xmlNode = XmlDocument.SelectSingleNode(textBoxModificationPath.Text);
                        if (xmlNode != null)
                        {
                            if (xmlNode.Attributes.Count > 0)
                            {
                                foreach (XmlAttribute attribute in xmlNode.Attributes)
                                {
                                    dropDownAttributeName.Items.Add(attribute.Name);
                                }
                            }
                        }
                    }
                    break;
            }
        }

        private void dataGridViewAttributes_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            UpdateModification();
        }

        private void dataGridViewAttributes_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            UpdateModification();
        }

        private void textBoxNodeName_Leave(object sender, EventArgs e)
        {
            UpdateModification();
        }

        private void dataGridViewAttributes_RowValidated(object sender, DataGridViewCellEventArgs e)
        {
            UpdateModification();
        }

        private void dropDownAttributes_Leave(object sender, EventArgs e)
        {
            UpdateModification();
        }

        private void textBoxAttributeValue_Leave(object sender, EventArgs e)
        {
            UpdateModification();
        }

        private void dropDownModificationType_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (dropDownModificationType.Text)
            {
                case "EnsureChildNode":
                    panelEnsureChildNode.Visible = true;
                    panelEnsureAttribute.Visible = false;
                    panelEnsureSection.Visible = false;

                    #region Update ValidationLogic

                    textBoxNodeName.CausesValidation = true; 
                    dropDownAttributeName.CausesValidation = false;
                    textBoxModificationValue.CausesValidation = false;
                    textBoxSectionName.CausesValidation = false;

                    #endregion

                    break;
                case "EnsureSection":
                    panelEnsureChildNode.Visible = false;
                    panelEnsureAttribute.Visible = false;
                    panelEnsureSection.Visible = true;

                    #region Update ValidationLogic

                    textBoxNodeName.CausesValidation = false; 
                    dropDownAttributeName.CausesValidation = false;
                    textBoxModificationValue.CausesValidation = false;
                    textBoxSectionName.CausesValidation = true;

                    #endregion

                    break;
                case "EnsureAttribute":
                    panelEnsureChildNode.Visible = false;
                    panelEnsureAttribute.Visible = true;
                    panelEnsureSection.Visible = false;

                    #region Update ValidationLogic

                    textBoxNodeName.CausesValidation = false; 
                    dropDownAttributeName.CausesValidation = true;
                    textBoxModificationValue.CausesValidation = true;
                    textBoxSectionName.CausesValidation = false;

                    #endregion

                    break;
            }

            errorProvider.SetError(textBoxModificationPath, String.Empty);
            errorProvider.SetError(textBoxModificationName, String.Empty);
            errorProvider.SetError(textBoxModificationValue, String.Empty);
            errorProvider.SetError(textBoxNodeName, String.Empty);
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            validatingAll = true;

            if (ValidateChildren())
            {
                this.DialogResult = DialogResult.OK;

                WebConfigModification = new WebConfigModification();
                WebConfigModification.Type = (WebConfigModificationType)Enum.Parse(typeof(WebConfigModificationType), dropDownModificationType.Text);
                WebConfigModification.Checked = true;
                WebConfigModification.Owner = textBoxModificationOwner.Text;
                WebConfigModification.Path = textBoxModificationPath.Text;
                WebConfigModification.Name = textBoxModificationName.Text;
                WebConfigModification.Value = textBoxModificationValue.Text;
                WebConfigModification.Sequence = 0;

                this.Close();
            }

            validatingAll = false;
        }

        private void textBoxSectionName_Leave(object sender, EventArgs e)
        {
            UpdateModification();
        }

        private void textBox_Validating(object sender, CancelEventArgs e)
        {
            TextBox textBox = sender as TextBox;

            if (String.IsNullOrEmpty(textBox.Text))
            {
                errorProvider.SetError(textBox, String.Format("{0} cannot be null.", textBox.Name.Replace("textBox", "")));

                if (validatingAll)
                {
                    e.Cancel = true;
                }
            }
            else
            {
                if(textBox.Equals(textBoxModificationPath))
                {
                    XmlNode xmlNode = XmlDocument.SelectSingleNode(textBoxModificationPath.Text);
                    if (xmlNode == null)
                    {
                        errorProvider.SetError(textBox, String.Format("Node '{0}' does not exist.", textBox.Text));

                        if (validatingAll)
                        {
                            e.Cancel = true;
                        }
                    }
                    else
                    {
                        errorProvider.SetError(textBox, String.Empty);
                    }
                }
                else
                {
                    errorProvider.SetError(textBox, String.Empty);
                }
            }
        }

        private void dropDown_Validating(object sender, CancelEventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;

            if (String.IsNullOrEmpty(comboBox.Text))
            {
                errorProvider.SetError(comboBox, String.Format("{0} cannot be null.", comboBox.Name.Replace("dropDown", "")));

                if (validatingAll)
                {
                    e.Cancel = true;
                }
            }
            else
            {
                errorProvider.SetError(comboBox, String.Empty);
            }
        }

        private void AddWebConfigModificationForm_Activated(object sender, EventArgs e)
        {
            textBoxModificationPath.Focus();
        }

        private void textBoxInnerXml_Leave(object sender, EventArgs e)
        {
            UpdateModification();
        }

        private void textBoxNodeName_Validating(object sender, CancelEventArgs e)
        {
            string errorMessage = IsNodeNameValid();

            if (string.IsNullOrEmpty(errorMessage))
            {
                errorProvider.SetError(textBoxNodeName, String.Empty);
            }
            else
            {
                errorProvider.SetError(textBoxNodeName, errorMessage);
                e.Cancel = true;
            }
        }

        #endregion

        #region Private Methods

        private string IsNodeNameValid()
        {
            string errorMessage = String.Empty;

            if (!String.IsNullOrEmpty(textBoxNodeName.Text))
            {
                try
                {
                    XmlDocument xmlDocument = new XmlDocument();
                    xmlDocument.CreateElement(textBoxNodeName.Text);
                }
                catch (Exception exception)
                {
                    errorMessage = exception.Message;
                }
            }

            return errorMessage;
        }

        private void UpdateModification()
        {
            if (String.IsNullOrEmpty(IsNodeNameValid()))
            {
                switch (dropDownModificationType.Text)
                {
                    case "EnsureChildNode":
                        string selectAttribute = String.Empty;
                        string nodeAttributes = String.Empty;
                        string innerXml = String.Empty;

                        StringBuilder attributesBuffer = new StringBuilder();

                        foreach (DataGridViewRow dataGridViewRow in dataGridViewAttributes.Rows)
                        {
                            object attributeName = dataGridViewRow.Cells[0].Value;
                            object attributeValue = dataGridViewRow.Cells[1].Value;

                            if (attributeName != null && attributeValue != null)
                            {
                                if (String.IsNullOrEmpty(selectAttribute))
                                {
                                    selectAttribute = String.Format("[@{0}='{1}']", attributeName, attributeValue);
                                }
                                attributesBuffer.Append(" ");
                                attributesBuffer.Append(String.Format("{0}='{1}'", attributeName, attributeValue));
                            }
                        }

                        nodeAttributes = attributesBuffer.ToString();

                        innerXml = textBoxInnerXml.Text ?? String.Empty;

                        if (!String.IsNullOrEmpty(textBoxNodeName.Text))
                        {
                            textBoxModificationName.Text = textBoxNodeName.Text + selectAttribute;
                            if (String.IsNullOrEmpty(innerXml))
                            {
                                textBoxModificationValue.Text = String.Format("<{0}{1}/>", textBoxNodeName.Text, nodeAttributes);
                            }
                            else
                            {
                                textBoxModificationValue.Text = String.Format("<{0}{1}>{3}{2}{3}</{0}>", textBoxNodeName.Text, nodeAttributes, innerXml, Environment.NewLine);
                            }
                        }
                        else
                        {
                            textBoxModificationName.Text = String.Empty;
                            textBoxModificationValue.Text = String.Empty;
                        }
                        break;
                    case "EnsureSection":
                        textBoxModificationName.Text = textBoxSectionName.Text;
                        textBoxModificationValue.Text = textBoxSectionName.Text;
                        break;
                    case "EnsureAttribute":
                        textBoxModificationName.Text = dropDownAttributeName.Text;
                        textBoxModificationValue.Text = textBoxAttributeValue.Text;
                        break;
                }

                if (!String.IsNullOrEmpty(textBoxModificationName.Text))
                {
                    errorProvider.SetError(textBoxModificationName, String.Empty);
                }
                else
                {
                    errorProvider.SetError(textBoxModificationName, String.Format("{0} cannot be null.", textBoxModificationName.Name.Replace("textBox", "")));
                }

                if (!String.IsNullOrEmpty(textBoxModificationValue.Text))
                {
                    errorProvider.SetError(textBoxModificationValue, String.Empty);
                }
                else
                {
                    errorProvider.SetError(textBoxModificationValue, String.Format("{0} cannot be null.", textBoxModificationValue.Name.Replace("textBox", "")));
                }
            }
        }

        private void UpdateFrequentlyUsedNodeNamesAutoComplete()
        {
            AutoCompleteStringCollection autoCompleteStringCollection = new AutoCompleteStringCollection();

            foreach (var item in ConfigurationHelper.FrequentlyUsedNodeNames)
            {
                autoCompleteStringCollection.Add(item.ToString());
            }

            textBoxNodeName.AutoCompleteCustomSource = autoCompleteStringCollection;
            textBoxSectionName.AutoCompleteCustomSource = autoCompleteStringCollection;
        }

        private void UpdateModifiationPathAutoComplete()
        {
            AutoCompleteStringCollection autoCompleteStringCollection = new AutoCompleteStringCollection();

            foreach (var item in WebConfigHelper.GetWebConfigNodes(XmlDocument))
            {
                autoCompleteStringCollection.Add(item.ToString());
            }

            textBoxModificationPath.AutoCompleteCustomSource = autoCompleteStringCollection;           
        }

        #endregion    
    }
}
